import { getBusinessObject, is } from "bpmn-js/lib/util/ModelUtil";
import { without } from "min-dash";

import { createModdleElement, getExtensionElementsList } from '@/utils/BpmnExtensionElementsUtil'

import editor from '@/store/editor'
import modeler from '@/store/modeler'
/////// 功能函数
export function getFormField(element) {
  const businessObject = getRelevantBusinessObject(element);

  if (!businessObject) return [];
  return getFormFieldList(businessObject) || [];
}

export function addFormFieid(
  element,
  property,
  fieldPropertiesList,
  fieldConstraintsList
) {
  try {
    const modeling =  modeler().getModeling
    const prefix = editor().getProcessEngine

    const businessObject = getRelevantBusinessObject(element);

    // 判断 extensionElements
    let extensionElements = businessObject.get("extensionElements");

    if (!extensionElements) {
      extensionElements = createModdleElement(
        "bpmn:ExtensionElements",
        { values: [] },
        businessObject
      );
      modeling?.updateModdleProperties(element, businessObject, {
        extensionElements
      });
    }

    // 判断 extensionElements 是否有 formData
    let formData = getFormData(businessObject);
    if (!formData) {
      formData = createModdleElement(
        `${prefix}:FormData`,
        { fields: [] },
        extensionElements
      );
      modeling?.updateModdleProperties(element, extensionElements, {
        values: [...extensionElements.get("values"), formData]
      });
    }

    // 创建新属性并添加
    const newFormField = createModdleElement(
      `${prefix}:FormField`,
      property,
      formData
    );

    // 创建约束条件
    if (fieldConstraintsList.length > 0) {
      addConstraints(element, newFormField, fieldConstraintsList);
    }

    // 创建字段属性
    if (fieldPropertiesList.length > 0) {
      addProperties(element, newFormField, fieldPropertiesList);
    }

    modeling?.updateModdleProperties(element, formData, {
      fields: [...formData.get("fields"), newFormField]
    });
  } catch (e) {
    console.log(e);
  }
}

function addConstraints(element, formField, fieldConstraintsList) {
  const modeling = modeler().getModeling
  const prefix = editor().getProcessEngine
  const newValidation = createModdleElement(
    `${prefix}:Validation`,
    { constraints: [] },
    formField
  );
  const constraints = [];
  fieldConstraintsList.forEach(constraint => {
    constraints.push(
      createModdleElement(`${prefix}:Constraint`, constraint, newValidation)
    );
  });
  modeling?.updateModdleProperties(element, newValidation, {
    constraints: constraints
  });
  modeling?.updateModdleProperties(element, formField, {
    validation: newValidation
  });
}

function addProperties(element, formField, fieldPropertiesList) {
  const modeling = modeler().getModeling
  const prefix = editor().getProcessEngine

  const newProperties = createModdleElement(
    `${prefix}:Properties`,
    { values: [] },
    formField
  );
  const propertys = [];
  fieldPropertiesList.forEach(constraint => {
    propertys.push(
      createModdleElement(`${prefix}:Property`, constraint, newProperties)
    );
  });
  modeling?.updateModdleProperties(element, newProperties, {
    values: propertys
  });
  modeling?.updateModdleProperties(element, formField, {
    properties: newProperties
  });
}

export function removeFormFieid(element, property) {
  const businessObject = getRelevantBusinessObject(element);
  const extensionElements = businessObject.get("extensionElements");
  const formData = getFormData(businessObject);
  if (!formData) return;

  const modeling = modeler().getModeling

  const fields = without(formData.get("fields"), property);
  modeling?.updateModdleProperties(element, formData, { fields });

  if (!fields || !fields.length) {
    modeling?.updateModdleProperties(element, extensionElements, {
      values: without(extensionElements.get("values"), formData)
    });
  }
}

///// helpers
function getRelevantBusinessObject(element) {
  const businessObject = getBusinessObject(element);
  if (is(element, "bpmn:Participant")) {
    return businessObject.get("processRef");
  }
  return businessObject;
}

function getFormFieldList(bo) {
  const properties = getFormData(bo);
  return properties && properties.get("fields");
}

function getFormData(bo) {
  const extensionElementsList = getExtensionElementsList(bo);
  const prefix = editor().getProcessEngine
  return extensionElementsList.filter(
    ex => ex.$type === `${prefix}:FormData`
  )?.[0];
}

export function isFormField(element) {
  const prefix = editor().getProcessEngine
  const businessObject = getBusinessObject(element);
  return (
    is(element, `${prefix}:FormSupported`) &&
    businessObject.get("formHandlerClass")
  );
}
